package com.yc.http.tomcat.impl;

import com.yc.http.tomcat.*;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class TomcatImpl implements Tomcat {
    // Servlet 容器
    private Map<String, HttpServlet> servletMap = new ConcurrentHashMap<>();

    public static final String WEB_ROOT =
            "D:\\_文件柜\\yc127_129\\yc127_129\\net-demo\\net-demo\\src\\main\\webapp";

    private static TomcatImpl tomcat;

    public static void main(String[] args) {
        tomcat = new TomcatImpl();
        // 启动服务
        Thread t = new Thread(()->{
            tomcat.start(8080);
        });
        // 设置精灵线程
        t.setDaemon(true);
        t.start();

        // 启动停止服务的监听
        try {
            ServerSocket ss = new ServerSocket(8009);
            Socket socket = ss.accept();
            // 验证请求的合法性, 如果合法, 则停止服务
            tomcat.stop();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    boolean running = true;
    @Override
    public void start(int port) {
        ServerSocket server = null;
        try {
            server = new ServerSocket(port);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        System.out.println("服务器启动: " + port);

        // 初始化Servlet容器, 将servlet创建并保存到集合中
        servletMap.put("/hello.s", new HelloServlet());
        servletMap.put("/like.s", new LikesServlet());
        servletMap.put("/index.s", new ToIndexServlet());
        servletMap.put("/", new ToIndexServlet());
        servletMap.put("/showCookie.s", new ShowCookie());
        servletMap.put("/addCookie.s", new AddCookieServlet());
        servletMap.put("/login.s", new LoginServlet());
        servletMap.put("/myname.s", new MynameServlet());
        servletMap.put("/logout.s", new LogoutServlet());

        for (HttpServlet servlet : servletMap.values()) {
            // 初始化
            servlet.init();
        }

        while (running) {
            try (Socket socket = server.accept()) {
//                InputStream in = socket.getInputStream();
//                OutputStream out = socket.getOutputStream();
                // 构建请求对象
                HttpServletRequest request = buildRequest(socket);
                // 构建响应对象
                HttpServletResponse response = buildResponse(socket, request);

                if(isServletRequest(request)){
                    // 判断是否是动态请求(Servlet请求)
                    processServletRequest(request,response);
                } else if(isStaticRequest(request)){
                    // 判断是否是静态请求(获取静态文件:html,css,js...)
                    processStaticRequest(request,response);
                } else {
                    // 404 目标资源不存在
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        for (HttpServlet servlet : servletMap.values()) {
            // 销毁
            servlet.destroy();
        }
    }

    @Override
    public HttpServletRequest buildRequest(Socket socket) throws IOException {
        return new HttpServletRequestImpl(socket);
    }

    @Override
    public HttpServletResponse buildResponse(Socket socket, HttpServletRequest request) throws IOException {
        return new HttpServletResponseImpl(socket);
    }

    @Override
    public boolean isStaticRequest(HttpServletRequest request) {
        // 127.0.0.1/index.html => WEB_ROOT + "/index.html"
        // 127.0.0.1/css/index.css => WEB_ROOT + "/css/index.css"
        String filepath = WEB_ROOT + request.getRequestURI();
        // 文件存在则是静态请求
        if(new File(filepath).exists()){
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean isServletRequest(HttpServletRequest request) {
        return servletMap.containsKey(request.getRequestURI());
    }

    @Override
    public void processStaticRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String filepath = WEB_ROOT + request.getRequestURI();
        // 获取输出流
        OutputStream out = response.getOutputStream();
        out.write("HTTP/1.1 200 OK\n".getBytes());
        // 响应体的格式说明
        String contentType = getMimeType(request.getRequestURI());
        out.write(("Content-Type: "+contentType+"\n").getBytes());
        // 空行
        out.write("\n".getBytes());
        // 响应体
        // 读取文件的输入流
        try(FileInputStream fis = new FileInputStream(filepath);){
            byte[] bytes = new byte[1024];
            int count;
            while((count=fis.read(bytes))>0){
                out.write(bytes,0,count);
            }
        }
    }

    @Override
    public void processServletRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        HttpServlet httpServlet = servletMap.get(request.getRequestURI());
        httpServlet.service(request,response);

        // 将会话id写入响应报文中
        HttpSession session = request.getSession();
        String id = session.getId();
        Cookie cookie = new CookieImpl("JSESSIONID", id);
        response.addCookie(cookie);

        response.flushBuffer();
    }

    @Override
    public String getMimeType(String path) {
        if(path.toLowerCase().endsWith(".html")){
            return "text/html;charset=utf-8";
        } else if(path.toLowerCase().endsWith(".css")){
            return "text/css;charset=utf-8";
        } else if(path.toLowerCase().endsWith(".js")){
            return "application/javascript;charset=utf-8";
        } else {
            return "text/html;charset=utf-8";
        }
    }

    @Override
    public void stop() {
        running = false;
    }
}
